from django.http import JsonResponse
from django.views import View
from django.utils import timezone
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator
from .models import Agent, DataSource
import json
import os
from datetime import datetime
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.triggers.interval import IntervalTrigger
from apscheduler.triggers.cron import CronTrigger
import logging

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger('agent_runner')

# 全局调度器实例
scheduler = None


def start_scheduler():
    """启动调度器并加载智能体任务"""
    global scheduler
    
    # 避免重复启动
    if scheduler and scheduler.running:
        logger.info('调度器已在运行中')
        return
    
    # 初始化调度器
    scheduler = BackgroundScheduler()
    scheduler.start()
    logger.info('调度器已启动')
    
    # 加载激活的智能体任务
    load_active_agent_tasks()
    
    # 确保在应用关闭时关闭调度器
    import atexit
    atexit.register(lambda: scheduler.shutdown() if scheduler else None)


def load_active_agent_tasks():
    """加载所有激活的智能体任务"""
    if not scheduler or not scheduler.running:
        logger.warning('调度器未运行，无法加载智能体任务')
        return
    
    # 获取所有激活的智能体
    active_agents = Agent.objects.filter(is_active=True)
    logger.info(f'发现 {active_agents.count()} 个激活的智能体')
    
    for agent in active_agents:
        # 先停止可能存在的相同任务
        stop_agent_schedule(agent)
        
        # 根据执行类型启动调度
        if agent.execution_type == 'interval' and agent.execution_interval:
            start_interval_execution(agent)
        elif agent.execution_type == 'cron' and agent.cron_expression:
            start_cron_execution(agent)
        # 被动执行不需要自动启动调度
        

def stop_agent_schedule(agent):
    """停止智能体的调度任务"""
    if not scheduler or not scheduler.running:
        return
    
    # 检查并移除间隔执行任务
    interval_job_id = f'agent_{agent.id}_interval'
    if scheduler.get_job(interval_job_id):
        scheduler.remove_job(interval_job_id)
        logger.info(f'已移除智能体 {agent.name} 的间隔执行任务')
    
    # 检查并移除定时执行任务
    cron_job_id = f'agent_{agent.id}_cron'
    if scheduler.get_job(cron_job_id):
        scheduler.remove_job(cron_job_id)
        logger.info(f'已移除智能体 {agent.name} 的定时执行任务')


@method_decorator(csrf_exempt, name='dispatch')
class AgentRunnerView(View):
    """智能体运行视图"""

    def get(self, request, *args, **kwargs):
        """处理GET请求，用于被动执行"""
        try:
            agent_id = request.GET.get('agent_id')

            # 验证智能体存在
            try:
                agent = Agent.objects.get(id=agent_id)
            except Agent.DoesNotExist:
                return JsonResponse({
                    'success': False,
                    'message': f'智能体ID {agent_id} 不存在'
                })

            # 检查是否为被动执行类型
            if agent.execution_type != 'passive':
                return JsonResponse({
                    'success': False,
                    'message': f'智能体 {agent.name} 不是被动执行类型'
                })

            # 运行智能体
            result = self.run_agent(agent)
            return JsonResponse({
                'success': True,
                'message': '智能体已成功运行',
                'result': result
            })

        except Exception as e:
            logger.error(f'被动执行智能体出错: {str(e)}')
            return JsonResponse({
                'success': False,
                'message': f'运行出错: {str(e)}'
            })

    def post(self, request, agent_id=None, *args, **kwargs):
        """处理智能体运行请求"""
        try:
            # 从URL参数获取agent_id，如果没有则从请求数据中获取
            if not agent_id:
                # 解析请求数据
                if request.content_type == 'application/json':
                    data = json.loads(request.body)
                else:
                    data = request.POST
                agent_id = data.get('agent_id')
            
            action = 'run'  # 对于URL路径请求，默认为run操作

            # 验证智能体存在
            try:
                agent = Agent.objects.get(id=agent_id)
            except Agent.DoesNotExist:
                return JsonResponse({
                    'success': False,
                    'message': f'智能体ID {agent_id} 不存在'
                })

            # 根据操作类型处理
            if action == 'run':
                # 手动运行智能体
                result = self.run_agent(agent)
                return JsonResponse({
                    'success': True,
                    'message': '智能体已成功运行',
                    'result': result
                })
            elif action == 'start_schedule':
                # 启动调度
                if agent.execution_type == 'interval' and agent.execution_interval:
                    self.start_interval_execution(agent)
                    if agent.execution_start_time and agent.execution_start_time > timezone.now():
                        return JsonResponse({
                            'success': True,
                            'message': f'已启动智能体 {agent.name} 的间隔执行，将在 {agent.execution_start_time} 开始，间隔为 {agent.execution_interval} 分钟'
                        })
                    else:
                        return JsonResponse({
                            'success': True,
                            'message': f'已启动智能体 {agent.name} 的间隔执行，间隔为 {agent.execution_interval} 分钟'
                        })
                elif agent.execution_type == 'cron' and agent.cron_expression:
                    self.start_cron_execution(agent)
                    return JsonResponse({
                        'success': True,
                        'message': f'已启动智能体 {agent.name} 的定时执行，表达式为 {agent.cron_expression}'
                    })
                elif agent.execution_type == 'passive':
                    return JsonResponse({
                        'success': True,
                        'message': f'智能体 {agent.name} 为被动执行类型，无需启动调度'
                    })
                else:
                    return JsonResponse({
                        'success': False,
                        'message': f'智能体 {agent.name} 的执行类型或配置无效'
                    })
            elif action == 'stop_schedule':
                # 停止调度
                self.stop_schedule(agent)
                return JsonResponse({
                    'success': True,
                    'message': f'已停止智能体 {agent.name} 的调度执行'
                })
            else:
                return JsonResponse({
                    'success': False,
                    'message': f'不支持的操作类型: {action}'
                })

        except json.JSONDecodeError:
            return JsonResponse({
                'success': False,
                'message': 'JSON解析错误'
            })
        except Exception as e:
            logger.error(f'智能体运行出错: {str(e)}')
            return JsonResponse({
                'success': False,
                'message': f'运行出错: {str(e)}'
            })

    def run_agent(self, agent):
        """运行智能体并返回结果"""
        logger.info(f'开始运行智能体: {agent.name}')

        result_data = {
            'agent_id': agent.id,
            'agent_name': agent.name,
            'execution_time': timezone.now().strftime('%Y-%m-%d %H:%M:%S'),
            'status': 'success',
            'message': '智能体执行成功',
            'data': {},
            'selected_tables': agent.selected_tables
        }

        try:
            # 1. 获取数据源信息
            datasource = agent.datasource
            logger.info(f'获取数据源信息: {datasource.name} ({datasource.engine})')

            # 2. 准备数据库连接参数
            db_params = {
                'host': datasource.host,
                'port': datasource.port,
                'database': datasource.database,
                'user': datasource.user,
                'password': datasource.password
            }

            # 3. 根据选择的表和字段生成查询并执行
            query_results = {}

            # 检查是否有选择的表
            if not agent.selected_tables:
                logger.warning(f'智能体 {agent.name} 没有选择任何表和字段')
                result_data['message'] = '未选择任何表和字段'
                result_data['status'] = 'warning'
            else:
                # 根据数据库类型选择不同的连接库
                if datasource.engine == 'mysql':
                    import pymysql
                    connection = pymysql.connect(**db_params)
                elif datasource.engine == 'postgresql':
                    import psycopg2
                    connection = psycopg2.connect(**db_params)
                elif datasource.engine == 'oracle':
                    import cx_Oracle
                    # Oracle连接字符串格式略有不同
                    dsn = cx_Oracle.makedsn(db_params['host'], db_params['port'], service_name=db_params['database'])
                    connection = cx_Oracle.connect(user=db_params['user'], password=db_params['password'], dsn=dsn)
                elif datasource.engine == 'sqlite':
                    import sqlite3
                    connection = sqlite3.connect(db_params['database'])
                else:
                    raise ValueError(f'不支持的数据库类型: {datasource.engine}')

                try:
                    cursor = connection.cursor()

                    # 遍历所有选择的表
                    for table_name, fields_list in agent.selected_tables.items():
                        # 字段列表不为空
                        if not fields_list:
                            logger.warning(f'表 {table_name} 没有选择任何字段')
                            continue

                        # 获取选择的字段
                        selected_fields = fields_list

                        # 生成SELECT语句
                        fields_str = ', '.join(selected_fields)
                        query = f'SELECT {fields_str} FROM {table_name}'
                        logger.info(f'执行查询: {query}')

                        # 执行查询
                        cursor.execute(query)
                        columns = [desc[0] for desc in cursor.description]
                        rows = cursor.fetchall()

                        # 转换结果为字典列表，处理Decimal类型
                        from decimal import Decimal
                        table_data = []
                        for row in rows:
                            row_dict = {}
                            for col, val in zip(columns, row):
                                # 检查是否为Decimal类型并转换为浮点数
                                if isinstance(val, Decimal):
                                    row_dict[col] = float(val)
                                elif isinstance(val, datetime):
                                    row_dict[col] = val.strftime('%Y-%m-%d %H:%M:%S')
                                else:
                                    row_dict[col] = val
                            table_data.append(row_dict)

                        query_results[table_name] = table_data
                        logger.info(f'表 {table_name} 查询完成，获取 {len(table_data)} 条记录')
                finally:
                    connection.close()

            # 4. 更新结果数据
            result_data['data'] = query_results

        except Exception as e:
            logger.error(f'智能体运行出错: {str(e)}')
            result_data['status'] = 'error'
            result_data['message'] = f'运行出错: {str(e)}'

        # 5. 更新智能体运行状态
        agent.last_run_time = timezone.now()
        agent.run_count += 1
        agent.save()

        # 6. 保存结果到文件
        # self.save_result(agent, result_data)

        logger.info(f'智能体 {agent.name} 运行完成')
        return result_data

    def save_result(self, agent, result_data):
        """保存运行结果到文件"""
        from db_config_project.settings import CONFIG_OUTPUT_DIR

        # 创建日期子目录
        date_str = datetime.now().strftime('%Y-%m-%d')
        date_dir = os.path.join(CONFIG_OUTPUT_DIR, date_str)
        os.makedirs(date_dir, exist_ok=True)

        # 生成文件名
        timestamp = datetime.now().strftime('%H-%M-%S')
        filename = f'agent_{agent.id}_{agent.name}_{timestamp}.json'
        filepath = os.path.join(date_dir, filename)

        # 保存结果
        with open(filepath, 'w', encoding='utf-8') as f:
            json.dump(result_data, f, ensure_ascii=False, indent=2)

        logger.info(f'智能体 {agent.name} 运行结果已保存到: {filepath}')

    def start_interval_execution(self, agent):
        """启动智能体间隔执行"""
        # 创建间隔触发器
        if agent.execution_start_time and agent.execution_start_time > timezone.now():
            # 如果设置了开始时间且尚未到达，则使用date参数
            trigger = IntervalTrigger(minutes=agent.execution_interval, start_date=agent.execution_start_time)
            logger.info(f'智能体 {agent.name} 将在 {agent.execution_start_time} 开始间隔执行')
        else:
            # 否则立即开始执行
            trigger = IntervalTrigger(minutes=agent.execution_interval)
            logger.info(f'智能体 {agent.name} 立即开始间隔执行')

        # 添加任务到调度器
        job_id = f'agent_{agent.id}_interval'
        scheduler.add_job(
            self.run_agent,
            trigger=trigger,
            args=[agent],
            id=job_id,
            replace_existing=True
        )

        logger.info(f'已添加智能体 {agent.name} 到间隔执行调度，任务ID: {job_id}')

    def start_cron_execution(self, agent):
        """启动智能体定时执行"""
        # 创建Cron触发器
        trigger = CronTrigger.from_crontab(agent.cron_expression)

        # 添加任务到调度器
        job_id = f'agent_{agent.id}_cron'
        scheduler.add_job(
            self.run_agent,
            trigger=trigger,
            args=[agent],
            id=job_id,
            replace_existing=True
        )

        logger.info(f'已添加智能体 {agent.name} 到定时执行调度，任务ID: {job_id}')

    def stop_schedule(self, agent):
        """停止智能体调度"""
        stop_agent_schedule(agent)